using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Volo.Abp;
using Volo.Abp.Autofac;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Json;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;

namespace OpenPasteSpider
{
    /// <summary>
    /// 
    /// </summary>
    [DependsOn(
        typeof(OpenPasteSpiderApplicationModule),
        typeof(OpenPasteSpiderEntityFrameworkCoreModule),
        typeof(AbpAutofacModule),
        typeof(AbpSwashbuckleModule)
        )]
    public class OpenPasteSpiderHttpApiHostModule : AbpModule
    {
        private const string DefaultCorsPolicyName = "Default";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void ConfigureServices(ServiceConfigurationContext context)
        {

            Console.WriteLine("--- OpenPasteSpiderHttpApiHostModule.ConfigureServices ---");
            var hostingEnvironment = context.Services.GetHostingEnvironment();

            //context.Services.ReplaceConfiguration(Program.Configuration);
            var Configuration = context.Services.GetConfiguration();

            //Console.WriteLine("ModuleConnectionConfig:");
            //Console.WriteLine(Configuration.GetValue<string>("ConnectionStrings:MainConnectionString"));
            //Console.WriteLine(Configuration.GetValue<string>("RedisConfig:MainConnection"));


            //链接信息
            //context.Services.Configure<OptionConnectionConfig>(Configuration.GetSection("ConnectionStrings"));//abc:abcitem

            //context.Services.Configure<OptionRedisConnectionConfig>(Configuration.GetSection("Redis"));//abc:abcitem

            //命令模板
            //context.Services.Configure<CommandInfo>(Configuration.GetSection("CommandInfo"));//abc:abcitem

            //系统设定信息
            context.Services.Configure<SpiderConfig>(Configuration.GetSection("SpiderConfig"));

            //redis的配置信息
            //context.Services.Configure<RedisConfig>(Configuration.GetSection("RedisConfig"));

            //context.Services.Configure<RabbitConfig>(Configuration.GetSection("RabbitConfig"));

            #region 格式化日期的输出
            context.Services.AddControllers().AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";

            });
            Configure<MvcNewtonsoftJsonOptions>(options =>
            {
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";//对类型为DateTime的生效
            });
            Configure<AbpJsonOptions>(options => options.DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss");  //对类型为DateTimeOffset生效

            Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
            Newtonsoft.Json.JsonConvert.DefaultSettings = new Func<Newtonsoft.Json.JsonSerializerSettings>(() =>
            {
                //日期格式化
                setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                //是否格式化换行便于阅读
                //setting.Formatting = Newtonsoft.Json.Formatting.Indented;
                //首字母小写
                setting.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
                return setting;
            });

            #endregion

            context.Services.AddHttpClient();

            //var configlist = Configuration.AsEnumerable();
            //var result = configlist.Where(x => x.Key.StartsWith("SpiderConfig:")).ToDictionary(x => x.Key.Replace("SpiderConfig:", ""), x => x.Value);
            //var config = Newtonsoft.Json.JsonConvert.DeserializeObject<SpiderConfig>(Newtonsoft.Json.JsonConvert.SerializeObject(result));
            //var _config = context.Services.GetRequiredService<SpiderConfig>();

            context.Services.AddMemoryCache();
            context.Services.AddSingleton<ICacheHelper, MemoryClient>();


            //以下的判断迁移到EF中了

            ////pssql
            //if (config.SqlDataType == "pgsql")
            //{
            //AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
            //context.Services.AddTransient<IOpenPasteSpiderDbContext, OpenPasteSpiderDbContext>();
            //context.Services.AddAbpDbContext<OpenPasteSpiderDbContext>(op =>
            //{
            //    Configure<AbpDbContextOptions>(aa => { aa.UseNpgsql(); });
            //});
            //}

            ////sqlitedata
            //if (config.SqlDataType == "sqlite")
            //{
            //    context.Services.AddTransient<IOpenPasteSpiderDbContext, SqliteDbContext>();
            //    context.Services.AddAbpDbContext<SqliteDbContext>(op =>
            //    {
            //        Configure<AbpDbContextOptions>(aa => { aa.UseSqlite(); });
            //    });
            //}

            ////mysql
            //if (config.SqlDataType == "mysql")
            //{
            //    context.Services.AddTransient<IOpenPasteSpiderDbContext, MysqlDbContext>();
            //    context.Services.AddAbpDbContext<MysqlDbContext>(op =>
            //    {
            //        Configure<AbpDbContextOptions>(aa => { aa.UseMySQL(); });
            //    });
            //}


            //设定api样式和前缀
            context.Services.Configure<Volo.Abp.AspNetCore.Mvc.AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(OpenPasteSpiderApplicationModule).Assembly, optio =>
                {
                    optio.UseV3UrlStyle = true;
                    optio.RootPath = "spider";
                });
            });


            context.Services.AddSwaggerGen(
                options =>
                {
                    //Bearer
                    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                    {
                        Name = "token",
                        Scheme = "",
                        Description = "在此输入token信息",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey
                    });

                    //添加文档
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "Support APP API", Version = "v1" });
                    options.DocInclusionPredicate((docname, description) =>
                    {
                        return description.RelativePath.IndexOf("spider") >= 0;
                    });
                    //options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                    //添加小锁
                    options.AddSecurityRequirement(new OpenApiSecurityRequirement() {
                       {new OpenApiSecurityScheme{ Reference=new OpenApiReference{ Type=ReferenceType.SecurityScheme,Id="Bearer" }},new string[]{ }}
                    });

                    options.ResolveConflictingActions(apidesc => apidesc.First());


                    //这里可以用isdevmodel来判断
                    if (System.IO.File.Exists(@"OpenPasteSpider.Application.xml")) { options.IncludeXmlComments(@"OpenPasteSpider.Application.xml"); }
                    if (System.IO.File.Exists(@"OpenPasteSpider.Application.Contracts.xml")) { options.IncludeXmlComments(@"OpenPasteSpider.Application.Contracts.xml"); }
                    if (System.IO.File.Exists(@"OpenPasteSpider.Domain.xml")) { options.IncludeXmlComments(@"OpenPasteSpider.Domain.xml"); }
                    if (System.IO.File.Exists(@"OpenPasteSpider.HttpApi.Host.xml")) { options.IncludeXmlComments(@"OpenPasteSpider.HttpApi.Host.xml"); }
                    //添加模块介绍
                    options.DocumentFilter<AuthTagDescriptions>();
                }
            );

            //全局处理异常信息
            context.Services.AddControllers(options =>
            {
                options.Filters.Add(typeof(CustomExceptionFilterAttribute));
                //options.Filters.Add(typeof(TheOneRole.CheckRoleAttribute));
            });

            context.Services.AddCors(options =>
            {
                options.AddPolicy(DefaultCorsPolicyName, builder =>
                {
                    builder
                        .WithOrigins(
                            Configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });

            //允许读取Post的body的内容
            context.Services.Configure<Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions>(x => x.AllowSynchronousIO = true).Configure<IISServerOptions>(x => x.AllowSynchronousIO = true);


            //context.Services.AddHostedService<SystemHostedService>();

            //var singlemodel = Configuration.GetValue<Boolean>("KeeperConfig:SingleModel");
            //if (!singlemodel)
            //{
            //    //context.Services.AddHostedService<SlaveHostedService>();
            //}

            context.Services.AddSingleton<LinkHelper>();

            context.Services.AddSingleton<CommandTaskHandler>();
            context.Services.AddSingleton<InitUpdateHandler>();
            context.Services.AddSingleton<NoticeTaskHanlder>();
            context.Services.AddSingleton<RecoveryTaskHandler>();
            //context.Services.AddSingleton<StatusTaskHandler>();




            ////启用mqpush
            //if (config.UseRabbit && !String.IsNullOrEmpty(config.GroupName))
            //{
            //    //暂时不启用，未完善
            //    //var _serviceprovider = context.Services.BuildServiceProvider();
            //    //var mqclientpush = _serviceprovider.GetRequiredService<RabbitMQClient>();
            //}


            var dev = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            if (!String.IsNullOrEmpty(dev) && dev == "Development")
            {
                Console.WriteLine("Is Development ReportHostedService and TaskHostedService No Start!");
            }
            else
            {
                context.Services.AddHostedService<SlaveHostedService>();
            }
            //context.Services.AddHostedService<SlaveHostedService>();
            //if (config.RecoveryDay > 0)
            //{
            //    context.Services.AddHostedService<RecoveryHostedService>();
            //}
            //if (config.StatusService)
            //{
            //    context.Services.AddHostedService<DockerStatusHostService>();
            //}
            //if (config.CommandService)
            //{
            //    context.Services.AddHostedService<CommandHostedService>();
            //    //context.Services.AddHostedService<MQHelperHostService>();
            //}
            //context.Services.AddHostedService<NoticeNotifyHandler>();

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            Console.WriteLine("--- OpenPasteSpiderHttpApiHostModule.PreConfigureServices ---");

            base.PreConfigureServices(context);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            Console.WriteLine("--- OpenPasteSpiderHttpApiHostModule.OnApplicationInitialization ---");
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors(DefaultCorsPolicyName);
            app.UseSwagger();

            app.UseAbpSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "SpiderAPI");
            });
            app.UseConfiguredEndpoints();

            //Console.WriteLine("-----------app setting finish! ----------------------");
        }
    }
}
